#ifndef TRANSPORT_SERIAL_H_
#define TRANSPORT_SERIAL_H_

#include <inttypes.h>
#include <vector>
#include <deque>
#include <queue>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/array.hpp>

#define SerialBufferSize 1024

class SerialParams
{
public:
    std::string serialPort;
    unsigned int baudRate;
    unsigned int flowControl;
    unsigned int parity;
    unsigned int stopBits;
    SerialParams() : serialPort(), baudRate(115200), flowControl(0), parity(0), stopBits(0)
    {
    }
    SerialParams(
        std::string _serialPort,
        unsigned int _baudRate,
        unsigned int _flowControl,
        unsigned int _parity,
        unsigned int _stopBits) : serialPort(_serialPort),
                                  baudRate(_baudRate),
                                  flowControl(_flowControl),
                                  parity(_parity),
                                  stopBits(_stopBits)
    {
    }
};

class SerialPort
{
public:
    bool ready;
    uint32_t total_recvbytes;

public:
    SerialPort(std::string url, int32_t buadrate);
    bool open();
    void run_forever();
    void loop();
    uint16_t read();
    void close();
    void write(std::vector<uint8_t> &data);
    bool is_timeout();
    void set_timeout(int t);
    uint16_t available(){
        return read_buffer_.size();
    }

private:
    void read_handler(const boost::system::error_code &ec, size_t bytesTransferred);
    void write_handler(const boost::system::error_code &ec);

private:
    boost::array<uint8_t, 1024> _buf;
    boost::shared_ptr<boost::asio::serial_port> port_;
    SerialParams params_;
    boost::thread thread_;
    // locks
    boost::mutex port_mutex;
    boost::mutex read_mutex;
    std::queue<std::vector<uint8_t>> send_buffer_;
    std::queue<uint8_t> read_buffer_;
    // for boost asio service
    boost::shared_ptr<boost::asio::io_service> ios_;
    boost::shared_ptr<boost::asio::deadline_timer> timer_;
};

#endif /* TRANSPORT_SERIAL_H_ */
